# 邻域搜索
import L_Critical
import I_GA_Util
import A_Choose_Util
import J_Fast_Sort

from G_Initial import *
import S_Draw
from  C_Load_Process_Map import *

# 局部搜索策略
# 两个算子 运行 知道个体得到改进   (死循环？)
# 输入：个体 加工图
# 输出：更新个体
def Local_Search_Djaya(Idv,Map):
    print("模块：Local_Search\t方法：Local_Search_Djaya(Idv,Map):")
    R_Random = random.uniform(0,1)
    New_Idv = Individual()
    if R_Random <= 0.7:
        New_Idv = L_Critical.Move_Ciritical_To_SameMachine(Idv, Map)
    else:
        New_Idv = Local_Search_Operator2(Idv,Map)
    return New_Idv

# 局部搜索算子2
# 移动Ratio高 负载机器高的 关键工序到 负载机器最低的机器加工
# 输入：个体 加工图
# 输出：新个体
def Local_Search_Operator2(Idv,Map):
    print("模块：Local_Search\t方法：Local_Search_Operator2(Idv,Map):")
    Critical_Flag,_,_,_,_ = L_Critical.Get_Critiacl_Operation(Idv, Map)
    Critical_Operator = []                      # 关键工序集合
    for i in range(Map.Chromosome_Length):      # 找到所有关键工序
        if Critical_Flag[i] != 0:
            Temp_Critical = []
            Temp_Critical.append(Idv.Job_Chromosome[i] - 1)                                 # 工件号
            Temp_Critical.append(L_Critical.Get_Operation_Order(Idv.Job_Chromosome, i) - 1)    # 工序号
            Critical_Operator.append(Temp_Critical)
    
    Machine_Workload,Machine_Assignment,Machine_Assignment_Time = GA_Util.Get_Machine_Process(Idv,Map)
    Max_Workload_Machine_Index = A_Choose_Util.Get_Max_Index(Machine_Workload)    # 最大负载机器下标

    Choose_Set =  Machine_Assignment[Max_Workload_Machine_Index]      # 负载最大机器的加工工序
    Choose_Critical_Set = []
    for i in range(len(Choose_Set)):                                   # 找到此机器上的关键工序
        if Choose_Set[i] in Critical_Operator:
            Choose_Critical_Set.append(Choose_Set[i])
    if len(Choose_Critical_Set) == 0:
        return Idv
    Ratio = [0] * len(Choose_Critical_Set)
    for i in range(len(Choose_Critical_Set)):
        Index = Choose_Set.index(Choose_Critical_Set[i])                # 在机器上第几个工序 找到加工时间
        Ratio[i] = Machine_Assignment_Time[Max_Workload_Machine_Index][Index] / (Choose_Critical_Set[i][1] + 1)

    Choose_Operator = Choose_Critical_Set[A_Choose_Util.Get_Max_Index(Ratio)]      # 挑选中的工序  准备转移加工机器的工序
    Choose_Operator_Map_Index = Map.Operation_Accessible_Machine_Index[Choose_Operator[0]][Choose_Operator[1]]
    # 挑选最小负载机器
    Min_Workload_Machine = []
    Min_Workload_Machine_Index = []
    for i in range(len(Choose_Operator_Map_Index)):
        Min_Workload_Machine.append(Machine_Workload[Choose_Operator_Map_Index[i]])
        Min_Workload_Machine_Index.append(Choose_Operator_Map_Index[i])

    _, _, Choose_Index = A_Choose_Util.Get_Min_Info_With(Min_Workload_Machine, Min_Workload_Machine_Index)
    Temp_Machine_Index = 0          # 确定更新的基因位的下标
    # 更新MS染色体
    for i in range(Choose_Operator[0]):         # 算上前面工件
        Temp_Machine_Index += Map.Operation_Num[i]

    Temp_Machine_Index += Choose_Operator[1]    # 此工件
    Idv.Machine_Chromosome[Temp_Machine_Index] = Choose_Index + 1
    # 更新个体
    New_Idv = Individual()
    New_Idv.Update_Chromosome(Idv.Job_Chromosome, Idv.Machine_Chromosome, Map)

    return New_Idv






